**核心执行流水线：**

```mermaid
graph LR
    A[类加载子系统] --> B[运行时数据区]
    B --> C[执行引擎]
    C --> D[垃圾收集系统]
    C --> E[解释器]
    C --> F[JIT编译器]
    style A fill:#e1f5fe
    style B fill:#f3e5f5
    style C fill:#e8f5e8
    style D fill:#fff3e0
```

**并行支撑体系：**

| 支撑系统               | 与执行引擎的关系 | 功能描述                     |
| ---------------------- | ---------------- | ---------------------------- |
| **字节码指令集**       | ✅ **执行基础**  | 定义执行引擎要执行的具体指令 |
| **Java 内存模型(JMM)** | ✅ **并发支撑**  | 保证多线程环境下执行的正确性 |
| **异常处理机制**       | ✅ **执行控制**  | 处理执行过程中的异常情况     |
| **本地方法接口(JNI)**  | ⚠️ **扩展能力**  | 提供执行 Native 代码的能力   |

### 3.1 类加载子系统 (Class Loading Subsystem)

| 加载阶段                    | 功能描述                  | 具体任务                                                                                                    | 异常类型                              |
| --------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| **加载 (Loading)**          | 查找并加载类的二进制数据  | 1. 通过全限定名获取二进制流<br/>2. 转换为方法区运行时数据结构<br/>3. 生成对应的 Class 对象                  | `ClassNotFoundException`              |
| **链接 (Linking)**          | 将类合并到 JVM 运行时状态 | 1. **验证**：确保类文件符合规范<br/>2. **准备**：为静态变量分配内存<br/>3. **解析**：将符号引用转为直接引用 | `VerifyError`, `NoClassDefFoundError` |
| **初始化 (Initialization)** | 执行类构造器`<clinit>()`  | 1. 为静态变量赋初值<br/>2. 执行静态代码块                                                                   | -                                     |

#### 类加载器体系

| 类加载器                    | 加载路径            | 负责加载的类         | 父加载器    |
| --------------------------- | ------------------- | -------------------- | ----------- |
| **Bootstrap ClassLoader**   | `JAVA_HOME/lib`     | Java 核心库 (rt.jar) | null (顶级) |
| **Extension ClassLoader**   | `JAVA_HOME/lib/ext` | 扩展库               | Bootstrap   |
| **Application ClassLoader** | 类路径 (classpath)  | 应用程序类           | Extension   |
| **Custom ClassLoader**      | 自定义              | 自定义类             | Application |

**类加载器双亲委派模型：**

```java
Bootstrap ClassLoader ← ExtClassLoader ← AppClassLoader ← 自定义ClassLoader
```

**双亲委派模型工作流程：**

1. **接收请求**：自定义类加载器收到加载请求
2. **向上委托**：逐级委托给父加载器（Application → Extension → Bootstrap）
3. **向下查找**：从 Bootstrap 开始逐级尝试加载
4. **结果返回**：找到则返回，找不到则由原始加载器尝试加载

### 3.2 运行时数据区 (Runtime Data Areas)

| 数据区            | 线程共享    | 功能描述                             | 配置参数            | 异常                 |
| ----------------- | ----------- | ------------------------------------ | ------------------- | -------------------- |
| **程序计数器**    | ❌ 线程私有 | 当前线程执行的字节码行号指示器       | -                   | -                    |
| **Java 虚拟机栈** | ❌ 线程私有 | 存储栈帧，包含局部变量表、操作数栈等 | `-Xss`              | `StackOverflowError` |
| **本地方法栈**    | ❌ 线程私有 | 为 Native 方法服务                   | -                   | `StackOverflowError` |
| **Java 堆**       | ✅ 线程共享 | 对象实例和数组的分配区域             | `-Xmx`, `-Xms`      | `OutOfMemoryError`   |
| **方法区**        | ✅ 线程共享 | 存储类信息、常量、静态变量等         | `-XX:MetaspaceSize` | `OutOfMemoryError`   |

#### 栈帧结构

| 组件             | 功能描述                   |
| ---------------- | -------------------------- |
| **局部变量表**   | 存储方法参数和局部变量     |
| **操作数栈**     | 执行字节码指令的工作区     |
| **动态链接**     | 指向运行时常量池的方法引用 |
| **方法返回地址** | 存储方法调用的返回位置     |

#### 堆内存分代模型

| 区域       | 对象生命周期   | GC 算法        | 配置参数            |
| ---------- | -------------- | -------------- | ------------------- |
| **新生代** | 新创建的对象   | Serial, ParNew | `-Xmn`              |
| **老年代** | 长期存活的对象 | CMS, G1        | -                   |
| **元空间** | 类元数据       | -              | `-XX:MetaspaceSize` |

#### 直接内存 (Direct Memory)

- **特点**：非运行时数据区的一部分，但频繁使用
- **功能**：NIO 使用的堆外内存
- **异常**：`OutOfMemoryError`
- **配置**：`-XX:MaxDirectMemorySize`

## 4. 垃圾收集器 (GC) 演进历程

**以下是 JVM 垃圾收集器的主要发展历程和技术演进表格：**

| 时期           | GC 名称     | 推出版本 | 核心技术              | 设计目标       | 优势                 | 局限性             | 地位演进             |
| -------------- | ----------- | -------- | --------------------- | -------------- | -------------------- | ------------------ | -------------------- |
| **初始阶段**   | Serial GC   | JDK 1.3  | 单线程 Stop-The-World | 基础回收功能   | 实现简单，无线程开销 | 停顿时间长         | 仍在小内存客户端使用 |
|                | Parallel GC | JDK 1.4  | 多线程并行回收        | 提高吞吐量     | 多核并行，吞吐量高   | 停顿时间仍较长     | 吞吐量应用首选       |
| **并发突破**   | CMS GC      | JDK 1.5  | 并发标记清除          | 降低停顿时间   | 并发执行，停顿短     | 内存碎片，CPU 敏感 | JDK 14 中废弃        |
|                | G1 GC       | JDK 7    | 分区算法 + 预测模型   | 平衡吞吐与延迟 | 可预测停顿，大堆友好 | 内存占用较高       | JDK 9+ 默认 GC       |
| **低延迟时代** | Shenandoah  | JDK 12   | 并发压缩算法          | 极低暂停时间   | 并发回收，停顿可控   | 性能开销较大       | 需要特定 JDK 发行版  |
|                | ZGC         | JDK 15   | 着色指针 + 负载屏障   | 亚毫秒级暂停   | 超大堆支持，停顿稳定 | 内存开销较大       | 生产就绪版本         |
| **特殊用途**   | Epsilon     | JDK 11   | 无回收机制            | 性能测试基准   | 无 GC 开销，极致性能 | 内存泄漏风险       | 测试和特殊场景使用   |

**Oracle JDK 各个版本默认 GC 演进**

| JDK 版本      | 发布年份  | 默认 GC                        | 重要变化说明                                  | 推荐替代参数                                        |
| ------------- | --------- | ------------------------------ | --------------------------------------------- | --------------------------------------------------- |
| **JDK 5-7**   | 2004-2011 | **Parallel GC** (吞吐量收集器) | 早期版本的统一选择，注重吞吐量                | 如需低延迟可手动启用 CMS: `-XX:+UseConcMarkSweepGC` |
| **JDK 8**     | 2014      | **Parallel GC**                | 延续之前版本的默认设置                        | G1 开始成熟: `-XX:+UseG1GC`                         |
| **JDK 9**     | 2017      | **G1 GC** (Garbage-First)      | **重大变革**：G1 成为新默认，平衡吞吐量和延迟 | 回退到 Parallel: `-XX:+UseParallelGC`               |
| **JDK 10**    | 2018      | **G1 GC**                      | 巩固 G1 的默认地位，持续优化                  | ZGC 开始引入(实验性)                                |
| **JDK 11**    | 2018      | **G1 GC**                      | LTS 版本，G1 进一步成熟                       | ZGC: `-XX:+UseZGC` (仍实验性)                       |
| **JDK 12-14** | 2019-2020 | **G1 GC**                      | 保持 G1 默认，Shenandoah 和 ZGC 持续改进      | Shenandoah: `-XX:+UseShenandoahGC`                  |
| **JDK 15**    | 2020      | **G1 GC**                      | ZGC 和 Shenandoah 成为生产就绪                | ZGC 正式可用: `-XX:+UseZGC`                         |
| **JDK 16-17** | 2021      | **G1 GC**                      | 当前 LTS 版本，G1 保持默认但 ZGC 成熟度更高   | 低延迟场景推荐 ZGC                                  |
| **JDK 18-21** | 2022-2023 | **G1 GC**                      | 最新版本，G1 仍是平衡性最好的默认选择         | ZGC 性能进一步优化                                  |

**OpenJDK 各个版本默认 GC 演进**

| OpenJDK 版本      | 发布年份  | 默认 GC         | 重要变化说明                  | 推荐替代参数                       |
| ----------------- | --------- | --------------- | ----------------------------- | ---------------------------------- |
| **OpenJDK 6-7**   | 2006-2011 | **Parallel GC** | 早期版本统一选择，注重吞吐量  | CMS: `-XX:+UseConcMarkSweepGC`     |
| **OpenJDK 8**     | 2014      | **Parallel GC** | 延续之前默认设置，G1 作为可选 | G1: `-XX:+UseG1GC`                 |
| **OpenJDK 9**     | 2017      | **G1 GC**       | **重大变革**：G1 成为新默认   | Parallel: `-XX:+UseParallelGC`     |
| **OpenJDK 10**    | 2018      | **G1 GC**       | 巩固 G1 默认地位              | ZGC 实验性: `-XX:+UseZGC`          |
| **OpenJDK 11**    | 2018      | **G1 GC**       | LTS 版本，G1 成熟稳定         | ZGC: `-XX:+UseZGC` (实验性)        |
| **OpenJDK 12-14** | 2019-2020 | **G1 GC**       | 保持 G1 默认，低延迟 GC 改进  | Shenandoah: `-XX:+UseShenandoahGC` |
| **OpenJDK 15**    | 2020      | **G1 GC**       | ZGC 和 Shenandoah 生产就绪    | ZGC: `-XX:+UseZGC`                 |
| **OpenJDK 16-17** | 2021      | **G1 GC**       | LTS 版本，ZGC 成熟度提升      | ZGC 低延迟场景                     |
| **OpenJDK 18-21** | 2022-2023 | **G1 GC**       | G1 保持默认，ZGC 持续优化     | ZGC 性能优化                       |

#### 规范要求的必须环节：

1. **类加载** - 必须支持加载、链接、初始化三个阶段
2. **内存划分** - 必须提供堆、栈、方法区等基本内存区域
3. **字节码执行** - 必须能够解释执行标准字节码指令
4. **自动内存管理** - 必须提供垃圾回收机制

#### 实现可优化的环节：

- 类加载的速度和缓存策略
- 内存分配的具体算法
- JIT 编译的优化程度
- 垃圾回收的效率和停顿时间

### 核心结论

**✅ JVM 规范定义了：**

- 核心执行流水线的**架构和流程**
- 各个组件的**职责和交互关系**
- 字节码的**语义和执行结果**

## 4. `.class`文件与类文件格式详解

.class 文件是 Java 编译后的二进制文件格式，包含了 Java 类或接口的完整定义，是 JVM 执行的基石。

#### .class 文件概览

```mermaid
graph TB
    A[.java 源文件] --> B[javac 编译器]
    B --> C[.class 字节码文件]
    C --> D[JVM 加载执行]

    style C fill:#e1f5fe
```

**核心特性：**

- ✅ 平台无关性 - 一次编译，到处运行
- ✅ 紧凑二进制格式 - 高效存储和传输
- ✅ 严格结构定义 - 符合 JVM 规范标准
- ✅ 包含元数据 - 类型、方法、字段等完整信息

#### .class 文件结构详解

**.class 文件二进制结构：**

```text
ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];
    u2             fields_count;
    field_info     fields[fields_count];
    u2             methods_count;
    method_info    methods[methods_count];
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}
```

**各组成部分详细说明**

| 组成部分                | 大小   | 描述                 | 示例值                       |
| ----------------------- | ------ | -------------------- | ---------------------------- |
| **魔数 (Magic Number)** | 4 字节 | 标识.class 文件格式  | `0xCAFEBABE`                 |
| **版本号**              | 4 字节 | 主版本号 + 次版本号  | JDK 8: 52.0<br/>JDK 11: 55.0 |
| **常量池计数器**        | 2 字节 | 常量池中常量的数量+1 | 根据类复杂度变化             |
| **常量池**              | 变长   | 字面量和符号引用表   | 包含类名、方法名等           |
| **访问标志**            | 2 字节 | 类的修饰符           | `ACC_PUBLIC`<br/>`ACC_FINAL` |
| **类索引**              | 2 字节 | 当前类的常量池索引   | 指向当前类名                 |
| **父类索引**            | 2 字节 | 父类的常量池索引     | 指向父类名                   |
| **接口计数器**          | 2 字节 | 实现的接口数量       | 0-n                          |
| **接口表**              | 变长   | 实现的接口索引数组   | 接口常量池索引               |
| **字段计数器**          | 2 字节 | 字段数量             | 根据字段数变化               |
| **字段表**              | 变长   | 字段信息数组         | 字段名、类型、修饰符         |
| **方法计数器**          | 2 字节 | 方法数量             | 根据方法数变化               |
| **方法表**              | 变长   | 方法信息数组         | 方法名、参数、字节码         |
| **属性计数器**          | 2 字节 | 属性数量             | 根据属性数变化               |
| **属性表**              | 变长   | 属性信息数组         | 源码文件、行号表等           |

#### 常量池详解

**常量池类型分类：**

| 类型标签 | 常量类型                      | 描述             | 结构                                    |
| -------- | ----------------------------- | ---------------- | --------------------------------------- |
| `1`      | `CONSTANT_Utf8`               | UTF-8 编码字符串 | `tag, length, bytes`                    |
| `3`      | `CONSTANT_Integer`            | 整型字面量       | `tag, bytes`                            |
| `4`      | `CONSTANT_Float`              | 浮点字面量       | `tag, bytes`                            |
| `5`      | `CONSTANT_Long`               | 长整型字面量     | `tag, high_bytes, low_bytes`            |
| `6`      | `CONSTANT_Double`             | 双精度字面量     | `tag, high_bytes, low_bytes`            |
| `7`      | `CONSTANT_Class`              | 类或接口符号引用 | `tag, name_index`                       |
| `8`      | `CONSTANT_String`             | 字符串字面量     | `tag, string_index`                     |
| `9`      | `CONSTANT_Fieldref`           | 字段符号引用     | `tag, class_index, name_and_type_index` |
| `10`     | `CONSTANT_Methodref`          | 方法符号引用     | `tag, class_index, name_and_type_index` |
| `11`     | `CONSTANT_InterfaceMethodref` | 接口方法符号引用 | `tag, class_index, name_and_type_index` |
| `12`     | `CONSTANT_NameAndType`        | 名称和类型描述符 | `tag, name_index, descriptor_index`     |

**方法表与字节码**

```text
method_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}
```

**重要的方法属性：**

- Code 属性 - 包含实际的字节码指令
- Exceptions 属性 - 方法声明的异常
- Signature 属性 - 泛型签名信息
- LineNumberTable - 行号与字节码的映射

#### 实际查看 .class 文件

**使用 javap 工具反编译：**

```bash
# 查看完整类信息
javap -verbose MyClass

# 仅查看常量池
javap -constants MyClass

# 查看字节码
javap -c MyClass
```

**示例输出片段：**

```text
Constant pool:
   #1 = Methodref          #6.#20         // java/lang/Object."<init>":()V
   #2 = Fieldref           #21.#22        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #23            // Hello World
   #4 = Methodref          #24.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #26            // MyClass

public void sayHello();
  Code:
     0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     3: ldc           #3                  // String Hello World
     5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     8: return
```

#### .class 文件的重要性

**对 JVM 的意义：**

- 🎯 执行基础 - JVM 直接执行的指令集
- 🎯 类型安全 - 验证阶段的重要依据
- 🎯 反射支持 - 元数据信息的来源
- 🎯 动态代理 - 运行时生成类的基础

**跨平台实现原理：**

```mermaid
graph LR
    A[Java 源码] --> B[平台无关的.class文件]
    B --> C[Windows JVM]
    B --> D[Linux JVM]
    B --> E[macOS JVM]
    C --> F[本地指令]
    D --> F
    E --> F
```

> .class 文件格式是 Java "一次编写，到处运行" 理念的技术基石，其精心设计的结构为 JVM 提供了丰富的元信息和可执行的字节码指令。

## 5. 加载阶段流程（类加载子系统）

### 类加载子系统的工作流程对应

**整体架构：**

```mermaid
graph TB
    A[类加载子系统] --> B[加载阶段]
    A --> C[链接阶段]
    A --> D[初始化阶段]

    B --> B1[查找二进制流]
    B --> B2[解析字节数据]
    B --> B3[创建Class对象]

    C --> C1[验证]
    C --> C2[准备]
    C --> C3[解析]

    D --> D1[执行<clinit>]
    D --> D2[静态变量赋值]
```

### 5.1 加载阶段详细流程

| 步骤                   | 具体操作                     | 技术细节                                                      | 输出结果             |
| ---------------------- | ---------------------------- | ------------------------------------------------------------- | -------------------- |
| **1. 查找二进制流**    | 根据全限定名定位.class 文件  | - 文件系统<br/>- JAR 包<br/>- 网络<br/>- 动态生成             | 类的二进制数据流     |
| **2. 解析字节数据**    | 将字节流转换为方法区数据结构 | - 验证魔数 0xCAFEBABE<br/>- 解析常量池<br/>- 解析字段和方法表 | 方法区中的类元数据   |
| **3. 创建 Class 对象** | 在堆中生成 Class 对象实例    | - 在堆中分配内存<br/>- 设置方法区引用<br/>- 初始化类静态信息  | java.lang.Class 实例 |

#### 加载阶段的技术实现

**类查找策略（双亲委派模型）：**

```java
// 类加载器查找顺序
1. 自定义ClassLoader.findClass()
2. Application ClassLoader
3. Extension ClassLoader
4. Bootstrap ClassLoader
```

#### 二进制流来源多样性：

- **本地文件系统** - 最常见的.class 文件
- **JAR/WAR 包** - 归档文件中的类
- **网络资源** - 远程加载的类
- **运行时生成** - 动态代理、字节码增强
- **数据库存储** - 持久化存储的类定义

### 5.2 链接阶段详细流程

链接阶段将加载后的类合并到 JVM 运行时状态，包含三个子阶段：

| 子阶段                  | 核心任务           | 具体操作                                                                   | 可能异常               |
| ----------------------- | ------------------ | -------------------------------------------------------------------------- | ---------------------- |
| **验证 (Verification)** | 确保类文件安全合规 | 1. 文件格式验证<br />2. 元数据验证<br />3. 字节码验证<br />4. 符号引用验证 | `VerifyError`          |
| **准备 (Preparation)**  | 为类变量分配内存   | 1. 分配静态变量内存<br />2. 设置默认初始值<br />3. 常量池内存分配          | -                      |
| **解析 (Resolution)**   | 符号引用转直接引用 | 1. 类/接口解析<br />2. 字段解析<br />3. 方法解析<br />4. 接口方法解析      | `NoClassDefFoundError` |

#### 验证阶段详解

**四级验证机制：**

```java
// 1. 文件格式验证
- 魔数0xCAFEBABE ✓
- 版本号兼容性 ✓
- 常量池类型正确 ✓

// 2. 元数据验证
- 父类存在性 ✓
- 最终类不被继承 ✓
- 抽象方法实现 ✓

// 3. 字节码验证
- 栈数据类型匹配 ✓
- 跳转指令有效性 ✓
- 类型转换安全 ✓

// 4. 符号引用验证
- 引用类可访问 ✓
- 字段/方法存在 ✓
```

#### 准备阶段详解

**静态变量内存分配规则：**

| 变量类型   | 初始值  | 说明           |
| ---------- | ------- | -------------- |
| `int`      | `0`     | 整型默认零值   |
| `long`     | `0L`    | 长整型默认零值 |
| `float`    | `0.0f`  | 浮点型默认零值 |
| `double`   | `0.0d`  | 双精度默认零值 |
| `boolean`  | `false` | 布尔型默认值   |
| `引用类型` | `null`  | 对象引用默认值 |

<Alert
  message="提示"
  description="准备阶段仅设置默认值，显式初始值在初始化阶段赋值"
  type="info"
  showIcon
/>
#### 解析阶段详解{" "}

**符号引用转换类型：**

```mermaid
graph LR
    A[符号引用] --> B[类/接口解析]
    A --> C[字段解析]
    A --> D[方法解析]
    A --> E[接口方法解析]

    B --> F[直接引用]
    C --> F
    D --> F
    E --> F
```

### 5.3 初始化阶段详细流程

初始化阶段是类加载过程的最后一步，执行类构造器 `<clinit>()` 方法，完成静态变量的显式初始化和静态代码块的执行。

| 关键特征     | 详细说明          | 触发条件                                                                                  |
| ------------ | ----------------- | ----------------------------------------------------------------------------------------- |
| **执行时机** | 类的首次主动使用  | 1. 创建实例<br />2. 访问静态字段<br />3. 调用静态方法<br />4. 反射调用<br />5. 初始化子类 |
| **执行内容** | `<clinit>()` 方法 | 1. 静态变量显式赋值<br />2. 静态代码块执行                                                |
| **线程安全** | JVM 保证同步      | 多线程环境下只有一个线程执行初始化                                                        |

#### `<clinit>()` 方法详解

**方法特性：**

```java
// <clinit>() 方法的特点
- ✨ 由编译器自动生成
- ✨ 收集所有静态变量赋值和静态代码块
- ✨ 按源码顺序合并执行
- ✨ 无需显式调用，JVM 自动触发
```

**执行顺序示例：**

```java
public class Example {
    // 静态变量声明
    private static int a = 1;          // 第一步：a = 1
    private static int b;

    // 静态代码块
    static {
        b = 2;                        // 第二步：b = 2
        System.out.println("静态块执行");
    }

    private static int c = initC();    // 第三步：c = 3

    private static int initC() {
        return 3;
    }
}
```

#### 初始化触发条件

**主动使用场景：**

| 场景类型         | 示例代码                     | 说明             |
| ---------------- | ---------------------------- | ---------------- |
| **创建实例**     | `new MyClass()`              | 最常见的触发方式 |
| **访问静态字段** | `MyClass.staticField`        | 非常量静态字段   |
| **调用静态方法** | `MyClass.staticMethod()`     | 任何静态方法调用 |
| **反射调用**     | `Class.forName("MyClass")`   | 显式类加载       |
| **子类初始化**   | `class Child extends Parent` | 父类先初始化     |

**不会触发初始化的场景：**

- ✅ 引用常量静态字段（编译期优化）
- ✅ 通过数组定义引用类
- ✅ 类名.class 语法
- ✅ ClassLoader.loadClass() 方法

#### 初始化顺序规则

**类初始化顺序：**

```mermaid
graph TB
    A[父类静态变量/块] --> B[子类静态变量/块]
    B --> C[父类实例变量/块]
    C --> D[父类构造器]
    D --> E[子类实例变量/块]
    E --> F[子类构造器]
```

**重要规则：**

- 父类优先：父类完全初始化后才初始化子类
- 顺序执行：静态变量和静态块按源码顺序执行
- 一次性质：每个类只初始化一次
- 线程安全：JVM 使用锁确保线程安全

** 初始化异常：**

| 异常类型                        | 触发场景         | 影响范围     |
| ------------------------------- | ---------------- | ------------ |
| **ExceptionInInitializerError** | 静态块抛出异常   | 类初始化失败 |
| **NoClassDefFoundError**        | 依赖类初始化失败 | 连锁反应     |

**异常示例：**

```java
// 循环依赖示例
class A {
    static int a = B.b + 1;  // 依赖B
}

class B {
    static int b = A.a + 1;  // 依赖A
}
// 结果：a=1, b=2 或 a=2, b=1（取决于加载顺序）
```

初始化阶段完成了类加载的最终准备工作，使得类可以被正常使用。
